// EMERGENT GAME TECHNOLOGIES PROPRIETARY INFORMATION
//
// This software is supplied under the terms of a license agreement or
// nondisclosure agreement with Emergent Game Technologies and may not 
// be copied or disclosed except in accordance with the terms of that 
// agreement.
//
//      Copyright (c) 1996-2008 Emergent Game Technologies.
//      All Rights Reserved.
//
// Emergent Game Technologies, Chapel Hill, North Carolina 27517
// http://www.emergent.net

#ifndef NITPTRSET_H
#define NITPTRSET_H

#include <GnTSet.h>

// This template class implements an unordered set. It is safe for smart
// pointer use.
template <class T, class TAlloc> class GnTPtrSet : public GnTSet<T, TAlloc>
{
public:
    GnTPtrSet(unsigned int uiInitialSize = 1);
    ~GnTPtrSet();

    void RemoveAt(unsigned int uiIndex);
    void OrderedRemoveAt(unsigned int uiIndex); // Preserve order.
    void RemoveAll();

private:
    // To prevent an application from inadvertently causing the compiler to
    // generate the default copy constructor or default assignment operator,
    // these methods are declared as private. They are not defined anywhere,
    // so code that attempts to use them will not link.
    GnTPtrSet(const GnTPtrSet&);
    GnTPtrSet& operator=(const GnTPtrSet&);
};

template <class T> class GnTObjectPtrSet: 
    public GnTPtrSet<T, GnTNewInterface<T> >
{
public:
    GnTObjectPtrSet(unsigned int uiInitialSize = 0);
};

template <class T> class GnTPrimitivePtrSet: 
    public GnTPtrSet<T, GnTMallocInterface<T> >
{
public:
    GnTPrimitivePtrSet(unsigned int uiInitialSize = 0);
};

//---------------------------------------------------------------------------
template <class T> inline
GnTObjectPtrSet<T>::GnTObjectPtrSet(unsigned int uiInitialSize) :
    GnTPtrSet<T, GnTNewInterface<T> >(uiInitialSize)
{
}
//---------------------------------------------------------------------------
template <class T> inline
GnTPrimitivePtrSet<T>::GnTPrimitivePtrSet(unsigned int uiInitialSize):
    GnTPtrSet<T, GnTMallocInterface<T> >(uiInitialSize)
{
}
//---------------------------------------------------------------------------
template <class T, class TAlloc> inline
GnTPtrSet<T, TAlloc>::GnTPtrSet(unsigned int uiInitialSize) :
    GnTSet<T, TAlloc>(uiInitialSize)
{
}
//---------------------------------------------------------------------------
template <class T, class TAlloc> inline
GnTPtrSet<T, TAlloc>::~GnTPtrSet()
{
    RemoveAll();
}
//---------------------------------------------------------------------------
template <class T, class TAlloc> inline
void GnTPtrSet<T, TAlloc>::RemoveAt(unsigned int uiIndex)
{
    GnAssert((uiIndex < GnTSet<T, TAlloc>::m_uiUsed));

    GnTSet<T, TAlloc>::m_pBase[uiIndex] =
        GnTSet<T, TAlloc>::m_pBase[--GnTSet<T, TAlloc>::m_uiUsed];
    GnTSet<T, TAlloc>::m_pBase[GnTSet<T, TAlloc>::m_uiUsed] = 0;
}
//---------------------------------------------------------------------------
template <class T, class TAlloc> inline
void GnTPtrSet<T, TAlloc>::OrderedRemoveAt(unsigned int uiIndex)
{
    GnAssert((uiIndex < GnTSet<T, TAlloc>::m_uiUsed));

    for (unsigned int ui = uiIndex; ui < GnTSet<T, TAlloc>::m_uiUsed - 1; ui++)
    {
        GnTSet<T, TAlloc>::m_pBase[ui] = GnTSet<T, TAlloc>::m_pBase[ui + 1];
    }
    GnTSet<T, TAlloc>::m_uiUsed--;
    GnTSet<T, TAlloc>::m_pBase[GnTSet<T, TAlloc>::m_uiUsed] = 0;
}
//---------------------------------------------------------------------------
template <class T, class TAlloc> inline
void GnTPtrSet<T, TAlloc>::RemoveAll()
{
    for (unsigned int ui = 0; ui < GnTSet<T, TAlloc>::m_uiUsed; ui++)
    {
        GnTSet<T, TAlloc>::m_pBase[ui] = 0;
    }
    GnTSet<T, TAlloc>::m_uiUsed = 0;
}
//---------------------------------------------------------------------------

#endif // #ifndef NITPTRSET_H
